<template>
  <div :style="maskContainer" id="vue-picture-viewer">
    <!-- 头部 -->
    <flexbox class="perview-header">
      <div class="left">{{imgIndex + 1}} / {{imgLength}}</div>
      <div class="center">{{bigImgName.slice(0,bigImgName.indexOf('.'))}}</div>
      <img class="close" @click="closeViewer" src="./img/pre_close.png" />
    </flexbox>
    <!-- 图片容器 -->
    <div class="imgContainer" ref="imgContainer" :style="imgContainer">
      <img :src="bigImgUrl" v-if="bigShowType.isImage" ref="bigImg" :style="bigImgStyle" />
      <flexbox class="file-show" v-if="!bigShowType.isImage">
        <div class="file-icon">
          <img :src="bigShowType.icon" />
        </div>
        <div class="file-handle">
          <el-button type="primary" @click.native="fileHandle('download')" plain>下载</el-button>
        </div>
      </flexbox>
      <!-- tips -->
      <transition name="fade">
        <div v-show="showTips" class="tips">{{tipsText}}</div>
      </transition>
    </div>
    <div class="fixedHandle">
      <!-- 操作按钮 -->
      <flexbox v-if="bigShowType.isImage" class="handleContainer">
        <img @click="enlarge" src="./img/pre_max.png" />
        <img @click="reduce" src="./img/pre_min.png" />
        <img style="padding: 4.5px;" @click="rotate" src="./img/pre_rotate.png" />
        <img @click="downloadImg(bigImgUrl, bigImgName)" src="./img/pre_down.png" />
      </flexbox>
      <!-- 缩略图容器 -->
      <div class="thumbnailContainer" v-if="imgLength > 1">
        <ul>
          <li ref="thumbnailItem" v-for="(item, index) in this.imgData" @click="switchImgUrl(index, $event)"
            :key="index">
            <img :src="item.url" v-if="isShowImage(item.url)" alt="">
            <img :src="getFileTypeIconWithSuffix(item.url)" v-if="!isShowImage(item.url)" alt="">
          </li>
        </ul>
      </div>
    </div>
    <!-- 左边箭头 -->
    <div class="leftArrowCon" @click="handlePrev" @mouseenter="enterLeft" @mouseout="outLeft">
      <img class="leftArrow" v-show="leftArrowShow" @click="enlarge" src="./img/pre_left.png" />
    </div>
    <!-- 右边箭头 -->
    <div class="rightArrowCon" @click="handleNext" @mouseenter="enterRight" @mouseout="outRight">
      <img class="rightArrow" v-show="rightArrowShow" src="./img/pre_right.png" />
    </div>
  </div>
</template>

<script>
  var env = require('zrender/lib/core/env')
  import {
    getMaxIndex,
    downloadImage
  } from '@/utils'

  export default {
    name: 'vue-picture-viewer',
    props: {
      imgData: {
        type: Array,
        default: () => {
          return []
        }
      },
      background: {
        type: String,
        default: 'rgba(0,0,0,0.4)'
      },
      // 选择的索引
      selectIndex: {
        type: Number,
        default: -1
      }
    },
    data() {
      return {
        // 默认不显示左右切换箭头
        leftArrowShow: false,
        rightArrowShow: false,
        // 图片容器数据
        rotateDeg: 0,
        bigImgUrl: '',
        bigShowType: {
          isImage: true,
          icon: ''
        }, //不是图片的时候 展示 icon
        bigImgName: '',
        imgLength: 0,
        imgIndex: 0,
        showTips: false,
        tipsText: '',
        bigImgConWidth: '',
        bigImgConHeight: '',
        maskContainer: {
          width: '100%',
          height: '100%',
          background: this.background,
          position: 'fixed',
          top: 0,
          left: 0,
          right: 0,
          bottom: 0
        },
        imgContainer: {
          width: 'auto',
          height: 'auto',
          position: 'absolute',
          top: '50%',
          left: '50%',
          'z-index': 100,
          transform: 'translate(-50%, -50%)'
        },
        bigImgStyle: {
          display: 'block',
          width: '80px',
          height: '80px',
          position: 'absolute',
          top: 50 + '%',
          left: 50 + '%',
          marginLeft: '',
          marginTop: '',
          userSelect: 'none'
        }
      }
    },
    mounted() {
      document
        .getElementById('vue-picture-viewer')
        .addEventListener('click', e => {
          e.stopPropagation()
        })

      this.imgLength = this.imgData.length
      this.imgIndex = this.selectIndex
      this.$nextTick(() => {
        this.bigImgUrl = this.imgData[this.imgIndex].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[this.imgIndex].name
        if (this.imgLength > 1) {
          // 大于1的时候才会展示缩略图
          var item = this.$refs.thumbnailItem
          item[this.imgIndex].className = 'borderActive'
        }
      })
      this.$refs.bigImg.onload = () => {
        this.init()
      }

      this.maskContainer['z-index'] = getMaxIndex()
    },
    methods: {
      // init
      init() {
        let screenW =
          document.documentElement.offsetWidth || document.body.offsetWidth
        let screenH =
          document.documentElement.scrollHeight || document.body.scrollHeight
        this.$nextTick(function () {
          const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
          for (let item of ratio) {
            if (
              this.$refs.bigImg.naturalWidth * item < screenW &&
              this.$refs.bigImg.naturalHeight * item < screenH - 200
            ) {
              this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
              this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
              this.imgContainer.width = this.bigImgConWidth + 'px'
              this.imgContainer.height = this.bigImgConHeight + 'px'
              this.bigImgStyle.width = this.bigImgConWidth + 'px'
              this.bigImgStyle.height = this.bigImgConHeight + 'px'
              this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
              this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
            }
          }
        })
      },
      // rotate init
      rotateInit() {
        let screenW =
          document.documentElement.offsetWidth || document.body.offsetWidth
        let screenH =
          document.documentElement.scrollHeight || document.body.scrollHeight
        const ratio = [0.1, 0.2, 0.3, 0.4, 0.5, 0.7, 0.8, 0.9]
        for (let item of ratio) {
          if (this.$refs.bigImg.naturalWidth * item < screenH - 160) {
            this.bigImgConWidth = this.$refs.bigImg.naturalWidth * item
            this.bigImgConHeight = this.$refs.bigImg.naturalHeight * item
            this.imgContainer.width = this.bigImgConWidth + 'px'
            this.imgContainer.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.width = this.bigImgConWidth + 'px'
            this.bigImgStyle.height = this.bigImgConHeight + 'px'
            this.bigImgStyle.marginLeft = -(this.bigImgConWidth / 2) + 'px'
            this.bigImgStyle.marginTop = -(this.bigImgConHeight / 2) + 'px'
          }
        }
      },
      // 放大
      enlarge() {
        this.$nextTick(function () {
          let screenW =
            document.documentElement.offsetWidth || document.body.offsetWidth
          let screenH =
            document.documentElement.scrollHeight || document.body.scrollHeight
          if (
            (this.$refs.bigImg.offsetWidth >= this.$refs.bigImg.offsetHeight &&
              this.$refs.bigImg.offsetHeight * 2 < screenH * 2) ||
            (this.$refs.bigImg.offsetHeight >= this.$refs.bigImg.offsetWidth &&
              this.$refs.bigImg.offsetWidth * 2 < screenW * 2)
          ) {
            this.$refs.bigImg.style.width =
              this.$refs.bigImg.offsetWidth * 1.3 + 'px'
            this.$refs.bigImg.style.height =
              this.$refs.bigImg.offsetHeight * 1.3 + 'px'
            this.$refs.bigImg.style.left = '50%'
            this.$refs.bigImg.style.top = '50%'
            this.bigImgStyle.marginLeft = -this.$refs.bigImg.offsetWidth / 2 + 'px'
            this.bigImgStyle.marginTop = -this.$refs.bigImg.offsetHeight / 2 + 'px'
          }
        })
      },
      // 缩小
      reduce() {
        if (this.$refs.bigImg.offsetWidth > 80) {
          /** 
             * clientWidth = width + padding
               offsetWidth = width + padding + border  */
          this.$refs.bigImg.style.width =
            this.$refs.bigImg.offsetWidth * 0.7 + 'px'
          this.$refs.bigImg.style.height =
            this.$refs.bigImg.offsetHeight * 0.7 + 'px'
          this.$refs.bigImg.style.left = '50%'
          this.$refs.bigImg.style.top = '50%'
          this.bigImgStyle.marginLeft = -this.$refs.bigImg.offsetWidth / 2 + 'px'
          this.bigImgStyle.marginTop = -this.$refs.bigImg.offsetHeight / 2 + 'px'
        }
      },
      // 旋转
      rotate() {
        if (this.rotateDeg === 0) {
          this.$refs.bigImg.style.transform = 'rotate(90deg)'
          this.rotateInit()
          this.rotateDeg++
        } else if (this.rotateDeg === 1) {
          this.$refs.bigImg.style.transform = 'rotate(180deg)'
          this.init()
          this.rotateDeg++
        } else if (this.rotateDeg === 2) {
          this.$refs.bigImg.style.transform = 'rotate(270deg)'
          this.rotateInit()
          this.rotateDeg++
        } else if (this.rotateDeg === 3) {
          this.$refs.bigImg.style.transform = 'rotate(360deg)'
          this.init()
          this.rotateDeg = 0
        }
      },
      // 点击缩略图切换图片
      switchImgUrl(num, e) {
        var item = this.$refs.thumbnailItem
        item.forEach(function (i) {
          i.className = ''
        })
        this.imgIndex = num
        this.bigImgUrl = this.imgData[num].url
        this.getShowTypeInfo(this.bigImgUrl)
        this.bigImgName = this.imgData[num].name
        e.currentTarget.className = 'borderActive'
        if (this.bigShowType.isImage) {
          this.init()
        }
      },
      // 切换到上一张
      handlePrev() {
        if (this.imgIndex <= 0) {
          this.tips('已经是第一张了!')
          this.imgIndex = 0
        } else {
          if (this.$refs.bigImg) {
            this.$refs.bigImg.style.transform = 'rotate(0deg)'
            this.rotateDeg = 0
          }

          this.imgIndex--
          this.bigImgUrl = this.imgData[this.imgIndex].url
          this.getShowTypeInfo(this.bigImgUrl)
          this.bigImgName = this.imgData[this.imgIndex].name
          var item = this.$refs.thumbnailItem
          item.forEach(function (i) {
            i.className = ''
          })
          item[this.imgIndex].className = 'borderActive'
          if (this.bigShowType.isImage) {
            this.init()
          }
        }
      },
      // 切换到下一张
      handleNext() {
        if (this.imgIndex + 1 >= this.imgData.length) {
          this.tips('已经是最后一张了!')
        } else {
          if (this.$refs.bigImg) {
            this.$refs.bigImg.style.transform = 'rotate(0deg)'
            this.rotateDeg = 0
          }

          this.imgIndex++
          this.bigImgUrl = this.imgData[this.imgIndex].url
          this.getShowTypeInfo(this.bigImgUrl)
          this.bigImgName = this.imgData[this.imgIndex].name

          var item = this.$refs.thumbnailItem
          item.forEach(function (i) {
            i.className = ''
          })
          item[this.imgIndex].className = 'borderActive'
          if (this.bigShowType.isImage) {
            this.init()
          }
        }
      },
      // 提示框
      tips(msg) {
        this.showTips = true
        this.tipsText = msg
        let _this = this
        setTimeout(function () {
          _this.showTips = false
        }, 10000)
      },
      // 下载图片
      downloadImg(data, filename) {
        downloadImage(data, filename)
      },
      // 鼠标左移
      enterLeft() {
        this.leftArrowShow = true
      },
      outLeft() {
        this.leftArrowShow = false
      },
      // 鼠标右移
      enterRight() {
        this.rightArrowShow = true
      },
      outRight() {
        this.rightArrowShow = false
      },
      // 关闭查看器
      closeViewer() {
        this.$emit('close-viewer')
      },
      /** 附件逻辑 */
      fileHandle(type) {
        var a = document.createElement('a')
        a.href = this.bigImgUrl
        a.download = this.bigImgName ? this.bigImgName : '文件'
        a.target = '_black'
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      },
      getShowTypeInfo(url) {
        let temps = url ? url.split('.') : []
        var ext = ''
        if (temps.length > 0) {
          ext = temps[temps.length - 1]
        } else {
          ext = ''
        }
        var icon = ''
        var isImage = true
        if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
          isImage = true
          icon = require('@/assets/img/file_img.png')
        } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
          isImage = false
          icon = require('@/assets/img/file_excle.png')
        } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
          isImage = false
          icon = require('@/assets/img/file_excle.png')
        } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
          isImage = false
          icon = require('@/assets/img/file_word.png')
        } else if (this.arrayContain(['rar', 'zip'], ext)) {
          isImage = false
          icon = require('@/assets/img/file_zip.png')
        } else if (ext === 'pdf') {
          isImage = false
          icon = require('@/assets/img/file_pdf.png')
        } else if (ext === 'ppt' || ext === 'pptx') {
          isImage = false
          icon = require('@/assets/img/file_ppt.png')
        } else if (this.arrayContain(['txt', 'text'], ext)) {
          isImage = false
          icon = require('@/assets/img/file_txt.png')
        } else {
          isImage = false
          icon = require('@/assets/img/file_unknown.png')
        }
        this.bigShowType = {
          isImage: isImage,
          icon: icon
        }
      },
      getFileTypeIconWithSuffix(url) {
        let temps = url ? url.split('.') : []
        var ext = ''
        if (temps.length > 0) {
          ext = temps[temps.length - 1]
        } else {
          ext = ''
        }
        if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
          return require('@/assets/img/file_img.png')
        } else if (this.arrayContain(['mp4', 'mp3', 'avi'], ext)) {
          return require('@/assets/img/file_excle.png')
        } else if (this.arrayContain(['xlsx', 'xls', 'XLSX', 'XLS'], ext)) {
          return require('@/assets/img/file_excle.png')
        } else if (this.arrayContain(['doc', 'docx', 'DOC', 'DOCX'], ext)) {
          return require('@/assets/img/file_word.png')
        } else if (this.arrayContain(['rar', 'zip'], ext)) {
          return require('@/assets/img/file_zip.png')
        } else if (ext === 'pdf') {
          return require('@/assets/img/file_pdf.png')
        } else if (ext === 'ppt' || ext === 'pptx') {
          return require('@/assets/img/file_ppt.png')
        } else if (this.arrayContain(['txt', 'text'], ext)) {
          return require('@/assets/img/file_txt.png')
        }
        return require('@/assets/img/file_unknown.png')
      },
      isShowImage(url) {
        let temps = url ? url.split('.') : []
        var ext = ''
        if (temps.length > 0) {
          ext = temps[temps.length - 1]
        } else {
          ext = ''
        }
        if (this.arrayContain(['jpg', 'png', 'gif', 'jpeg'], ext)) {
          return true
        }
        return false
      },
      arrayContain(array, string) {
        return array.some(item => {
          return item === string
        })
      }
    },
    beforeDestroy() {
      if (document.getElementById('vue-picture-viewer')) {
        document
          .getElementById('vue-picture-viewer')
          .removeEventListener('click', e => {
            e.stopPropagation()
          })
      }
    }
  }

</script>

<style lang="scss" scoped>
  .perview-header {
    width: 100%;
    height: 40px;
    background: rgba(0, 0, 0, 0.6);
    color: rgba(255, 255, 255, 0.8);
    line-height: 40px;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 101;
    padding: 10px;

    .left {
      flex-shrink: 0;
      font-size: 14px;
    }

    .center {
      text-align: center;
      flex: 1;
      padding: 0 20px;
    }

    .close {
      display: block;
      padding: 8px;
      width: 40px;
      height: 40px;
      cursor: pointer;
    }
  }

  .leftArrowCon {
    width: 30%;
    height: calc(100% - 40px);
    background: transparent;
    position: absolute;
    top: 40px;
    left: 0;
    z-index: 98;
    cursor: pointer;
  }

  .rightArrowCon {
    width: 30%;
    height: calc(100% - 40px);
    background: transparent;
    position: absolute;
    top: 40px;
    right: 0;
    z-index: 99;
    cursor: pointer;
  }

  .leftArrow {
    position: absolute;
    top: 50%;
    left: 30px;
    margin-top: -60px;
    transition: all 0.5s;
    width: 50px;
    height: 50px;
    pointer-events: none;
  }

  .rightArrow {
    position: absolute;
    top: 50%;
    right: 30px;
    margin-top: -60px;
    width: 50px;
    height: 50px;
    transition: all 0.5s;
    pointer-events: none;
  }

  .imgContainer .tips {
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    text-align: center;
    line-height: 40px;
    position: absolute;
    left: 50%;
    top: 50%;
    min-width: 150px;
    margin-left: -60px;
    margin-top: -20px;
    border-radius: 6px;
    padding: 4px 4px;
    font-size: 14px;
  }

  .fixedHandle {
    width: 800px;
    height: 140px;
    position: fixed;
    left: 50%;
    bottom: 0;
    margin-left: -400px;
    overflow: hidden;
    z-index: 100;
  }

  .handleContainer {
    width: 210px;
    height: 40px;
    background: rgba(0, 0, 0, 0.6);
    line-height: 40px;
    border-radius: 20px;
    position: absolute;
    left: 50%;
    bottom: 100px;
    padding: 0 14px;
    margin-left: -100px;

    img {
      display: block;
      width: 40px;
      height: 40px;
      padding: 8px;
      margin: 0 2px;
      cursor: pointer;
    }
  }

  .handleItem {
    width: 28px;
    height: 28px;
    color: white;
  }

  ul {
    padding: 0;
    margin: 0;
  }

  ul li {
    list-style: none;
    display: inline-block;
    width: 30px;
    height: 30px;
    margin-left: 20px;
    cursor: pointer;
  }

  .thumbnailContainer {
    max-width: 800px;
    background: rgba(255, 255, 255, 0.7);
    position: absolute;
    left: 50%;
    bottom: 0;
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    transform: translate(-50%, 0%);
    overflow-x: auto;
    overflow-y: hidden;
  }

  .thumbnailContainer ul {
    padding-top: 10px;
    padding-bottom: 10px;
    text-align: center;
    white-space: nowrap;
  }

  .thumbnailContainer ul li {
    display: inline-block;
    width: 38px;
    height: 38px;
    box-sizing: content-box;
    margin-left: 10px;
    user-select: none;
  }

  .thumbnailContainer ul li:last-child {
    margin-right: 10px;
  }

  .thumbnailContainer ul li img {
    display: inline-block;
    width: 38px;
    height: 38px;
    border-radius: 3px;
    box-sizing: content-box;
  }

  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 1s;
  }

  .fade-enter,
  .fade-leave-to {
    opacity: 0;
  }

  /* 添加border */
  .borderActive {
    box-shadow: 0px 4px 7px 0px rgb(241, 140, 112);
  }

  /* 修改原生的滚动条 */
  ::-webkit-scrollbar {
    /* 血槽宽度 */
    width: 8px;
    height: 8px;
  }

  ::-webkit-scrollbar-thumb {
    /* 拖动条 */
    background: rgba(0, 0, 0, 0.3);
    border-radius: 6px;
  }

  ::-webkit-scrollbar-track {
    /* 背景槽 */
    background: #ddd;
    border-radius: 6px;
  }

  /** 文件展示*/
  .file-show {
    position: absolute;
    top: 60%;
    left: 50%;
    width: 450px;
    height: 260px;
    margin-top: -150px;
    margin-left: -225px;
    background-color: white;
    border-radius: 3px;
    padding: 0 80px;

    .file-icon {
      flex: 1;

      img {
        display: block;
        width: 100px;
      }
    }

    .file-handle {
      button {
        display: block;
        width: 120px;
        margin-left: 0;
        margin-right: 0;
        height: 34px;
      }

      button:first-child {
        margin-bottom: 20px;
      }
    }
  }

</style>
